﻿/*   
    Copyright (C) 2009 Galaktika Corporation ZAO

    This file is a part of Galaktika.BusinessMonitor
 
    Galaktika.BusinessMonitor is a free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
      
    You should have received a copy of the GNU General Public License
    along with Galaktika.BusinessMonitor.  If not, see <http://www.gnu.org/licenses/>.
  
    If GPL v.3 is not suitable for your products or company,
    Galaktika Corp provides Galaktika.BusinessMonitor under a flexible commercial license
    designed to meet your specific usage and distribution requirements.
    If you have already obtained a commercial license from Galaktika Corp,
    you can use this file under those license terms.
*/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Galaktika.BI.Charting;
using Galaktika.BI.Extensibility.Dom;
using Galaktika.BI.Runtime;
using Galaktika.BI.Runtime.Services;
using System.Windows.Controls.Primitives;
using Galaktika.BI.Extensibility;

namespace Galaktika.BI.Silverlight.Controls
{
    public partial class SwitchButton : SimpleButton
    {
        private float m_PenWidth;
        private List<SwitchButton> m_ListSwitchButtons = new List<SwitchButton>();

        public SwitchButton()
        {
            base.IsToggleButton = true;
            this.AChecked = false;
            m_PenWidth = 3;
            this.AColorBorderPush = Colors.Black;
            this.AColorBorderRelease = Colors.LightGray;
            base.DefaultStyleKey = typeof(SwitchButton);
        }


        #region Appearance
        [Browsable(false)]
        [DefaultValue(false)]
        public bool AStretchImage { get; set; }

        private int m_MarginImage = 3;
        [Browsable(false)]
        public int AMarginImage
        {
            get
            {
                return m_MarginImage;
            }
            set
            {
                if (value > 0)
                    m_MarginImage = value;
            }
        }

        [Browsable(false)]
        public float APenWidth
        {
            get
            {
                return this.m_PenWidth;
            }
            set
            {
                if (value > 0)
                    this.m_PenWidth = value;
            }
        }

        [Browsable(false)]
        public Color AColorBorderPush { get; set; }

        [Browsable(false)]
        public Color AColorBorderRelease { get; set; }

        private string m_AssemblyPush = "";
        [Browsable(false)]
        public string AAssemblyPush
        {
            get
            {
                return m_AssemblyPush;
            }
            set
            {
                m_AssemblyPush = value;
            }
        }

        private string m_ResNamePush = "";
        [Browsable(false)]
        public string AResNamePush
        {
            get
            {
                return m_ResNamePush;
            }
            set
            {
                m_ResNamePush = value;
            }
        }

        private string m_AssemblyRelease = "";
        [Browsable(false)]
        public string AAssemblyRelease
        {
            get
            {
                return m_AssemblyRelease;
            }
            set
            {
                m_AssemblyRelease = value;
            }
        }

        private string m_ResNameRelease = "";
        [Browsable(false)]
        public string AResNameRelease
        {
            get
            {
                return m_ResNameRelease;
            }
            set
            {
                m_ResNameRelease = value;
            }
        }
        #endregion

        #region Data Properties

        [Browsable(false)]
        public bool AChecked { get; set; }

        private string m_Variable = "";
        [Browsable(false)]
        public string AVariable
        {
            get
            {
                return m_Variable;
            }
            set
            {
                m_Variable = value;
            }
        }

        [Browsable(false)]
        [DefaultValue(0)]
        public long AValueMask { get; set; }

        [Browsable(false)]
        [DefaultValue(false)]
        public bool AInGroup { get; set; }

        #endregion Data Properties

        protected override void OnClick()
        {
            base.OnClick();
            btnContent_Click(this, null);
        }

        private void btnContent_Click(object sender, RoutedEventArgs e)
        {
            var taskMgr = this.Context.Services.GetService<IUserTaskManager>();
            if (taskMgr != null)
            {
                taskMgr.RunTaskAsync(string.Format(Localization.AppTask_SwitchButtonModifyVariable, base.Name), state =>
                {
                    try
                    {
                        long varValue;
                        long varMask = this.AValueMask;
                        if (this.AInGroup)
                        {
                            varValue = varMask;
                            this.AChecked = true;
                        }
                        else
                        {
                            bool newStateChecked = !this.AChecked;
                            varValue = this.GetButtonVariableValue(this);
                            if (newStateChecked)
                            {
                                varValue = this.SetValueOfMask(varValue,
                                                               varMask);
                            }
                            else
                            {
                                varValue = this.ResetValueOfMask(varValue,
                                                                 varMask);
                            }

                            this.AChecked = (varValue & varMask) != 0;
                        }

                        this.SetButtonVariableValue(this, varValue);
                    }
                    finally
                    {
                        taskMgr.Dispatcher.BeginInvoke(() => this.UpdateView());
                    }
                });
            }
        }

        private long GetButtonVariableValue(SwitchButton btn)
        {
            long varResult = 0;

            if ((btn == null) || (btn.AVariable == string.Empty))
            {
                return varResult;
            }


            if (btn.Context != null)
            {
                IExecutionContext context = (IExecutionContext)btn.Context.Services.GetService(typeof(IExecutionContext));
                if (context != null)
                {
                    BrickVariable var = context.GetVariable(btn.Context, btn.AVariable, true);
                    long.TryParse(var.CurrentValue, out varResult);
                }

            }

            return varResult;
        }

        private void SetButtonVariableValue(SwitchButton btn, long value)
        {
            if ((btn == null) || (btn.AVariable == string.Empty))
                return;

            if (btn.Context != null)
            {
                IExecutionContext context = (IExecutionContext)btn.Context.Services.GetService(typeof(IExecutionContext));
                if (context != null)
                {
                    // устанавливаю в переменную новое значение
                    context.ModifyVariable(btn.Context, btn.AVariable, value.ToString());
                }
            }
        }

        // Устанавливает значение value по маске mask
        private long SetValueOfMask(long value, long mask)
        {
            return value |= mask;
        }

        // Сбрасывает значение value по маске mask
        private long ResetValueOfMask(long value, long mask)
        {
            return value &= ~(mask);
        }

        // Сбрасывает биты всех кнопок с именем переменной VariableName
        private long ResetValueInGroup(string varName, long valueCur)
        {
            if (string.IsNullOrEmpty(varName))
            {
                return valueCur;
            }

            long valueNew = valueCur;
            foreach (SwitchButton btn in this.m_ListSwitchButtons)
            {
                if (btn.AChecked && btn.AInGroup && btn.AVariable.Equals(varName))
                {
                    valueNew = this.ResetValueOfMask(valueNew, btn.AValueMask);
                    btn.AChecked = false;
                }
            }

            return valueNew;
        }


        // Сбрасывает значение m_Checked всех кнопок с именем переменной VariableName
        private void ResetCheckedInGroup(string varName)
        {
            if (string.IsNullOrEmpty(varName))
            {
                return;
            }

            foreach (SwitchButton btn in this.m_ListSwitchButtons)
            {
                if (btn.AChecked && btn.AInGroup && btn.AVariable.Equals(varName))
                {
                    btn.AChecked = false;
                }
            }
        }

        // Инициализация состояния кнопки
        private void InitButtonState()
        {
            long varLong = GetButtonVariableValue(this);
            long varMask = this.AValueMask;

            // при нахождении кнопки в группе будет устанавливаться только та кнопка
            // значение маски которой совпадает со значением переменной
            if (this.AInGroup)
            {
                this.AChecked = (varLong == varMask);
            }
            else
            {
                this.AChecked = ((varLong & varMask) != 0);
            }
        }

        public override void EndEdit()
        {            
            //TODO: Перерисовка
            //Разобраться с картинками. заменить когда будет собрана dll-ка с картинками.
            var taskMgr = this.Context.Services.GetService<IUserTaskManager>();
            taskMgr.RunTaskAsync(string.Format(Localization.AppTask_ProcessingProperties, base.Name),
                state =>
                {
                    InitButtonState();
                    taskMgr.Dispatcher.BeginInvoke(() => this.UpdateView());
                });

        }

        private void UpdateView()
        {
            (this.Content as StackPanel).Children.Clear();

            string assemblyName = this.AChecked ? this.AAssemblyPush : this.AAssemblyRelease;
            string resourceName = this.AChecked ? this.AResNamePush : this.AResNameRelease;

            if (!string.IsNullOrEmpty(resourceName))
            {
                Image im = new Image()
                {
                    Stretch = Stretch.None
                };
                im.Source =
                    UriResources.GetImage(UriResources.GetResourceString(
                        assemblyName,
                        resourceName.Remove(0, assemblyName.Length + 1)));
                (this.Content as StackPanel).Children.Add(im);
            }
            else
            {
                TextBlock tb = new TextBlock();
                tb.Text = this.AText;
                (this.Content as StackPanel).Children.Add(tb);
            }

            this.IsChecked = this.AChecked;
        }
    }
}
